/**
 * 解析请求路径参数对象
 * @param {string} url 请求路径
 */
function getObjectFromUrl(url) {
	let tempObj = {};
	if (/\?/.test(url)) {
		let paramStr = url.substring(url.indexOf("?") + 1);
		let paramArray = paramStr.split("&");
		paramArray.forEach(item => {
			let resultArray = item.split("=");
			tempObj[resultArray[0]] = resultArray[1];
		});
	}
	return tempObj;
}

/**
 * 获取路径 参数字串
 * @param {object} params 参数对象
 */
function appendParam(params, appendMark = true) {
	if (typeof params == 'object') {
		let keys = Object.keys(params);
		if (keys && keys.length > 0) {
			let list = keys.map(item => {
				return `${item}=${params[item]}`;
			})
			return `${appendMark?'?':''}${list.join("&")}`
		}
		return "";
	} else {
		throw new Error("Params 类型错误")
	}
}
/**
 * 拨打电话
 * @param {string} phoneNumber 电话号码
 */
function callPhoneNumber(phoneNumber) {
	if (!phoneNumber) return;
	uni.makePhoneCall({
		phoneNumber,
	}).catch((error) => {
		errorPrint(error.errMsg);
	})
}

// 定义一个函数，用于将电话号码中的部分字符替换为指定字符
function privatePhone(phone, start = 3, end = 7, replace = '*') {
	// 如果电话号码为空，则直接返回空
	if (!phone) return phone;
	if (phone.length < 4) {
		// 如果phone的长度小于4，则start为0，end为phone的长度
		start = 0;
		end = phone.length;
	} else if (phone.length < 8) {
		// 如果phone的长度小于8，则end为phone的长度
		end = phone.length;
	}
	// 计算需要替换的字符长度，如果end-start大于0，则取end-start，否则取0
	const length = (end - start) > 0 ? (end - start) : 0;
	// 如果replace存在，则取replace，否则取*
	const replaceChar = replace ? replace : "*";
	// 定义一个空字符串，用于存储替换后的字符
	let replaceText = "";
	// 循环length次，将replaceChar添加到replaceText中
	for (let index = 0; index < length; index++) {
		replaceText = `${replaceText}${replaceChar}`;
	}
	return phone.replace(phone.substring(start, end), replaceText)
}

// 定义一个函数，用于将名字中的空格替换为星号
function privateName(name) {
	// 如果名字为空，则直接返回
	if (!name) return name;
	// 将名字中的空格替换为空字符串
	name = name.replace(" ", "");
	// 定义一个空字符串，用于存储结果
	let result = "";
	// 将名字转换为数组
	name = name.split("");
	// 遍历数组中的每个字符
	name.forEach((item) => {
		// 如果结果为空，则将当前字符赋值给结果
		if (!result) {
			result = item;
		} else {
			result = `${result}*`
		}
	})
	return result;
}

// 定义一个函数，用于隐藏价格中的数字
function privatePrice(price, type = 'hideHead') {
	// 如果price不是字符串类型，则将其转换为字符串类型
	if (typeof price != 'string') price = String(price);
	// 如果type为hideTail，则隐藏价格中的尾部数字
	if (type == 'hideTail') {
		// 获取价格中的第一个数字
		const first = price[0];
		// 将价格中的所有数字替换为*
		price = price.replace(/\d/g, "*");
		// 将价格中的第一个数字替换为*
		price = price.substring(1, price.length);
		// 将第一个数字和*拼接起来
		price = `${first}${price}`;
		// 如果type为hideHead，则隐藏价格中的头部数字
	} else if (type == 'hideHead') {
		// 将价格中的第一个数字替换为*
		price = price.substring(1, price.length);
		// 将*和剩余的价格拼接起来
		price = `*${price}`;
		// 否则，隐藏价格中的所有数字
	} else {
		price = price.replace(/\d/g, "*");
	}
	return price;
}

/**
 * 判断是否为数组
 * @param {Object} data
 */
function isArray(data) {
	return Object.prototype.toString.call(data) === '[object Array]';
}

// 判断数据是否为空
function isEmpty(data, onlyNull = false) {
	// 如果onlyNull为true，则判断数据是否为null或undefined
	if (onlyNull) {
		return data === null || data === undefined;
	} else {
		// 如果数据类型为对象
		if (typeof data == 'object') {
			// 如果数据不为空
			if (data) {
				// 将数据转换为JSON字符串
				let result = JSON.stringify(data);
				// 判断JSON字符串是否为空对象或空数组
				return result == "{}" || result == "[]"
			} else {
				// 如果数据为空，则返回true
				return true;
			}
		} else {
			// 如果数据类型不为对象，则判断数据是否为空
			return data ? false : true;
		}
	}
}

// 判断数据是否不为空
function isNotEmpty(data, onlyNull = false) {
	// 调用isEmpty函数，判断数据是否为空，如果为空，则返回false，否则返回true
	return !isEmpty(data, onlyNull);
}

// 是否是空id
function isEmptyId(id) {
	return isEmpty(id) || id == '0' || id == 'null' || id == 'undefined';
}

// 是否不是空id
function isNotEmptyId(id) {
	return !isEmptyId(id);
}

/**
 * 版本比对
 * @param {Object} versionA 
 * @param {Object} versionB
 * @returns 1 versionA 大于 versionB || -1 versionA 小于 versionB || 0 两个version相等
 */
// 比较两个版本号的大小
function compareVersion(versionA, versionB) {
	// 将版本号A按"."分割成数组
	const versionArr_A = versionA.split(".");
	// 将版本号B按"."分割成数组
	const versionArr_B = versionB.split(".");
	// 获取两个数组中长度较大的值
	const maxLength = Math.max(versionArr_A.length, versionArr_B.length);
	// 遍历数组
	for (let i = 0; i < maxLength; i++) {
		// 获取数组A中第i个元素，如果不存在则默认为0
		const a = versionArr_A[i] || 0;
		// 获取数组B中第i个元素，如果不存在则默认为0
		const b = versionArr_B[i] || 0;
		// 将元素转换为数字进行比较
		if (Number(a) > Number(b)) {
			// 如果数组A中的元素大于数组B中的元素，则返回1
			return 1;
		} else if (Number(a) < Number(b)) {
			// 如果数组A中的元素小于数组B中的元素，则返回-1
			return -1;
		}
		// 如果遍历到最后一个元素，则返回0
		if (i === maxLength - 1) {
			return 0;
		}
	}
}

// 用于比较两个对象是否相等
function cmp(x, y) {
	// 判断双方是否都为null或undefined，亦或者严格相等，则返回true
	if (x === y) {
		return true;
	}
	// 如果不严格相等，则判断双方是否都为对象
	// 如果双方不是对象，则返回false
	if (!(x instanceof Object) || !(y instanceof Object)) {
		return false;
	}
	// 如果都为对象，则判断双方是否为同一个对象
	// 判断构造函数是否相同，继承属性
	if (x.constructor !== y.constructor) {
		return false;
	}
	// 如果构造函数相同，则判断双方是否有不同的自有属性
	// 遍历x对象的属性
	for (var p in x) {
		// 继承属性已经判断完成
		// 需要判断自有属性
		if (x.hasOwnProperty(p)) {
			// Allows comparing x[ p ] and y[ p ] when set to undefined  
			// 如果x有自有属性p，而y没有，则返回false
			if (!y.hasOwnProperty(p)) {
				return false;
			}
			// 如果x[p] 和 y[p]严格相等，继续下个遍历
			if (x[p] === y[p]) {
				continue;
			}
			// 如果不严格相等，并且x[p]为非对象类型，说明不同，返回false
			if (typeof(x[p]) !== "object") {
				return false;
			}
			// 如果x[p]为对象类型，则递归调用cmp函数，判断x[p]和y[p]是否相等
			if (!cmp(x[p], y[p])) {
				return false;
			}
		}
	}
	// 遍历完了x，反过来遍历比对一下Y有没有X没有的属性
	for (p in y) {
		if (y.hasOwnProperty(p) && !x.hasOwnProperty(p)) {
			return false;
		}
	}
	return true;
}

/**
 * 获取UUID
 */
function getUUID() {
	if (typeof crypto === 'object') {
		if (typeof crypto.randomUUID === 'function') {
			return crypto.randomUUID();
		}
		if (typeof crypto.getRandomValues === 'function' && typeof Uint8Array === 'function') {
			const callback = (c) => {
				const num = Number(c);
				return (num ^ (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (num / 4)))).toString(16);
			};
			return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, callback);
		}
	}
	let timestamp = new Date().getTime();
	let perforNow = (typeof performance !== 'undefined' && performance.now && performance.now() * 1000) || 0;
	return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
		let random = Math.random() * 16;
		if (timestamp > 0) {
			random = (timestamp + random) % 16 | 0;
			timestamp = Math.floor(timestamp / 16);
		} else {
			random = (perforNow + random) % 16 | 0;
			perforNow = Math.floor(perforNow / 16);
		}
		return (c === 'x' ? random : (random & 0x3) | 0x8).toString(16);
	});
}

/** 获取服务供应商 */
function getProvider(service) {
	if (['oauth', 'share', 'payment', 'push'].includes(service)) {
		return new Promise((resolve, reject) => {
			uni.getProvider({
				service,
				success: (res) => {
					resolve(res)
				},
				fail: (err) => {
					reject(err.errMsg);
				}
			})
		})
	} else {
		throw new Error(`getProvider service error: ${service}`)
	}
}

/** 检查用户授权 */
function checkAuthSetting(settingName, callback) {
	// #ifndef APP || APP-PLUS || APP-ANDROID || APP-IOS
	return new Promise((resolve, reject) => {
		uni.getSetting({
			success: (getSettingRes) => {
				if (getSettingRes.authSetting[`scope.${settingName}`] == undefined) { // 未接受或拒绝过此权限
					uni.authorize({
						scope: `scope.${settingName}`,
						success: (authorizeRes) => { // 同意授权
							if (typeof callback == 'function') callback(true);
							resolve();
						},
						fail: (authorizeError) => {
							let errMsg = authorizeError.errMsg || `未授权: ${settingName}`
							if (typeof callback == 'function') callback(false, errMsg);
							reject(errMsg);
						}
					})
				} else if (getSettingRes.authSetting[`scope.${settingName}`] == false) { // 拒绝权限
					return openSettingView(settingName, callback);
				} else { // 已授权
					if (typeof callback == 'function') callback(true);
					resolve();
				}
			}
		})
	})
	// #endif
	// #ifdef APP || APP-PLUS || APP-ANDROID || APP-IOS
	if (typeof callback == 'function') callback(true);
	return Promise.resolve();
	// #endif

}
/** 打开授权页面 */
function openSettingView(settingName, callback) {
	return new Promise((resolve, reject) => {
		uni.openSetting({
			success: (res) => {
				if (res.authSetting[`scope.${settingName}`]) { // 同意授权
					if (typeof callback == 'function') callback(true)
					resolve();
				} else {
					let errMsg = `未授权：${settingName}`
					if (typeof callback == 'function') callback(false, errMsg)
					reject(errMsg);
				}
			},
			fail: (error) => {
				let errMsg = error.errMsg || 'openSetting 失败'
				if (typeof callback == 'function') callback(false, errMsg)
				reject(errMsg)
			}
		})
	})
}

/**
 * 遍历对比枚举对象
 * @param {*} enumObj 枚举对象
 * @param {*} value 需对比的值 
 * @param {*} compareKey 需对比的key
 * @returns 
 */
function ergodicEnum(enumObj, value, compareKey = 'value') {
	let result = null;
	if (value == null || value == undefined) return result;
	if (typeof enumObj == 'object') {
		if (enumObj instanceof Array) {
			enumObj.map((item, index) => {
				return {
					...item,
					index
				}
			}).forEach((item) => {
				if (value == item[compareKey]) {
					result = item;
				}
			})
		} else {
			Object.keys(enumObj).forEach((keyItem, keyIndex) => {
				let item = {
					...enumObj[keyItem],
					index: keyIndex
				};
				if (value == item[compareKey]) {
					result = item;
				}
			})
		}
	}
	return result;
}

/**
 * 获取枚举对象中指定value的name
 * @param {*} enumObj 枚举对象
 * @param {*} value 需对比的值 
 * @param {*} compareKey 需对比的key
 * @returns 
 */
function getEnumValueName(enumObj, value, compareKey = 'value') {
	let result = ergodicEnum(enumObj, value, compareKey);
	if (result) {
		return result.name;
	} else {
		return "";
	}
}

/**
 * 获取枚举对象中指定value的index
 * @param {*} enumObj 
 * @param {*} value 
 * @param {*} compareKey 
 * @returns 
 */
function getEnumValueIndex(enumObj, value, compareKey = 'value') {
	let result = ergodicEnum(enumObj, value, compareKey);
	if (result) {
		return result.index;
	} else {
		return -1;
	}
}

/**
 * 获取枚举对象中指定name的value
 * @param {*} enumObj 枚举对象
 * @param {*} name 需对比的值 
 * @param {*} compareKey 需对比的key
 * @returns 
 */
function getEnumNameValue(enumObj, name, compareKey = 'name') {
	let result = ergodicEnum(enumObj, name, compareKey);
	if (result) {
		return result.value;
	} else {
		return '';
	}
}

/**
 * 获取枚举对象中指定name的index
 * @param {*} enumObj 枚举对象
 * @param {*} name 需对比的值 
 * @param {*} compareKey 需对比的key
 * @returns 
 */
function getEnumNameIndex(enumObj, name, compareKey = 'name') {
	let result = ergodicEnum(enumObj, name, compareKey);
	if (result) {
		return result.index;
	} else {
		return -1;
	}
}

/**
 * 获取枚举对象中指定index的value
 * @param {*} enumObj 枚举对象
 * @param {*} index 需对比的值 
 * @param {*} compareKey 需对比的key
 * @returns 
 */
function getEnumIndexValue(enumObj, index, compareKey = 'index') {
	let result = ergodicEnum(enumObj, index, compareKey);
	if (result) {
		return result.value
	} else {
		return ""
	}
}

/**
 * 获取枚举对象中指定index的name
 * @param {*} enumObj 枚举对象
 * @param {*} index 需对比的值 
 * @param {*} compareKey 需对比的key
 * @returns 
 */
function getEnumIndexName(enumObj, index, compareKey = 'index') {
	let result = ergodicEnum(enumObj, index, compareKey);
	if (result) {
		return result.name
	} else {
		return ""
	}
}

import {
	ENUM_MEDIA_TYPE
} from "../../static/enum.js"

/**
 * 根据资源路径 判断 是图片还是视频
 * @param {*} mediaPath 
 * @returns 
 */
function analyticsMediaType(mediaPath) {
	let imageSub = [".jpg", ".png", ".svg", ".webp", ".gif", ".jpeg"];
	let videoSub = [".mp4", ".mov", ".m4v", ".3gp", ".avi", ".m3u8", ".webm"];
	let mediaType = ENUM_MEDIA_TYPE.UNKNOWN;
	if (mediaPath && typeof mediaPath == 'string') {
		mediaPath = mediaPath.toLowerCase();
		imageSub.forEach(subItem => {
			if (mediaPath.indexOf(subItem) != -1) {
				mediaType = ENUM_MEDIA_TYPE.IMAGE
			}
		})
		videoSub.forEach(subItem => {
			if (mediaPath.indexOf(subItem) != -1) {
				mediaType = ENUM_MEDIA_TYPE.VIDEO
			}
		})
	}
	return mediaType;
}


/**
 * rpx 转 px
 * @param {*} rpx
 * @returns
 */
// rpx2px 计算结果缓存
const rpxChangeMap = {};

function rpx2px(rpx) {
	if (rpx === 0) return 0;
	let result = rpxChangeMap[rpx];
	if (!result) {
		let deviceWidth = uni.getSystemInfoSync().windowWidth; //获取设备屏幕宽度
		let px = (deviceWidth / 750) * Number(rpx)
		result = Math.floor(px);
		rpxChangeMap[rpx] = result;
	}
	return result;
}

/**
 * px 转 rpx
 * @param {*} px 
 * @returns 
 */
// px2rpx 计算结果缓存
const pxChangeMap = {};

function px2rpx(px) {
	if (px === 0) return 0;
	let result = pxChangeMap[px];
	if (!result) {
		let deviceWidth = uni.getSystemInfoSync().windowWidth; //获取设备屏幕宽度
		let rpx = (750 / deviceWidth) * Number(px)
		result = Math.floor(rpx);
		pxChangeMap[px] = result;
	}
	return result;
}

/**
 * 订阅消息
 * @param {Object} messageTemplateIds
 * @param {Object} callback
 */
function subscribeMessage(messageTemplateIds, callback) {
	// #ifdef MP-WEIXIN
	uni.requestSubscribeMessage({
		tmplIds: messageTemplateIds,
		success: (res) => {
			const subscribeResult = res;
			delete subscribeResult.errMsg;
			printDebug("订阅消息", subscribeResult, messageTemplateIds);
			if (typeof callback == 'function') {
				callback(true, subscribeResult);
			}
		},
		fail: (error) => {
			if (typeof callback == 'function') {
				callback(false, error);
			}
		}
	})
	// #endif
	// #ifndef MP-WEIXIN
	if (typeof callback == 'function') callback(true);
	// #endif
}

/**
 * 获取数组随机索引
 * @param {Number} arrayLength 
 * @returns 
 */
function getArrayRandomIndex(arrayLength) {
	return Math.floor(Math.random() * arrayLength);
}

module.exports = {
	getObjectFromUrl,
	appendParam,

	callPhoneNumber,

	privatePhone,
	privateName,
	privatePrice,

	isArray,
	isEmpty,
	isNotEmpty,
	isEmptyId,
	isNotEmptyId,

	compareVersion,
	cmp,

	getUUID,

	getProvider,
	checkAuthSetting,
	openSettingView,

	ergodicEnum,
	getEnumValueName,
	getEnumValueIndex,
	getEnumNameValue,
	getEnumNameIndex,
	getEnumIndexValue,
	getEnumIndexName,

	analyticsMediaType,

	px2rpx,
	rpx2px,

	subscribeMessage,

	getArrayRandomIndex
}